#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define LIMIT_MIN_ERR 1  /* 至少30个字节 */
#define NO_EXISTS_ERR   2  /* 文件不存在 */
#define NO_IS_FILE_ERR 3  /* 不是一个文件 */
 
// ./t3 a.txt
int main(int argc, const char *argv[]){
    if(argc != 2) return -1;

    if(fork() == 0){
        // 子进程（儿子）
        // 1. 验证文件是否存在
        struct stat st;
        if(stat(argv[1], &st) != 0) _exit(NO_EXISTS_ERR); 

        // 2. 验证是否为文件
        if(! S_ISREG(st.st_mode))  _exit(NO_IS_FILE_ERR); 

        // 3. 验证文件大小是否小于30个字节
        if(st.st_size < 30)  _exit(LIMIT_MIN_ERR); 

        // 4. 3个进程平分读取字节数
        int avg_bytes = st.st_size / 3; 

        // 5. 打开文件
        int fd = open(argv[1], O_RDONLY);
        // 6. for循环创建3个子进程（孙子）
        int i = 0;
        for(;i<3; i++){
            if(fork() == 0){
                break;
            }
        }

        while(i < 3){
            // 孙进程 的工作
            lseek(fd, i*avg_bytes, SEEK_SET);
            char buf[10] = "";
            ssize_t total = 0;
             printf(
                "------pid(%d),ppid(%d),pgid(%d) reading-----\n",
                getpid(), getppid(), getpgid(getpid())
            );
            while(total < avg_bytes){
                total += read(fd, buf, 10);
                printf("%s",buf);
                bzero(buf, 10);
            }
            printf(
                "------pid(%d),ppid(%d),pgid(%d) readed-----\n",
                getpid(), getppid(), getpgid(getpid())
            );

            _exit(0);
        }
        
        pid_t pid; 
        while( (pid=waitpid(0, NULL, WCONTINUED|WUNTRACED)) != -1){
            printf("%d 子进程结束\n", pid);
        }

        close(fd);
        _exit(0);
    }
    int s;
    while( wait(&s) != -1){
        if(WIFEXITED(s)) s = WEXITSTATUS(s);
        switch (s)
        {
        case LIMIT_MIN_ERR:
            printf("%s 文件大小至于30个字节!\n", argv[1]);
            break;
        case NO_EXISTS_ERR:
            printf("%s 文件不存在!\n", argv[1]);
            break;
        
        case NO_IS_FILE_ERR:
            printf("%s 不是一个可读的文本文件!\n", argv[1]);
            break;
        
        case 0:
            printf("OK\n");
            break;
        }
    }
    printf("----over---\n");
    return 0;
}